package com.distribution.system.openapi.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.distribution.common.exception.ApiParamValidException;
import com.distribution.common.utils.StringUtils;
import com.distribution.system.domain.bo.ChoosePhoneResultBO;
import com.distribution.system.domain.dto.ChoosePhoneDTO;
import com.distribution.system.domain.dto.SendCodeDTO;
import com.distribution.system.domain.dto.PlaceOrderDTO;
import com.distribution.system.domain.entity.CmccDaProduct;
import com.distribution.system.domain.entity.CmccDaOrder;
import com.distribution.system.domain.req.ReqResult;
import com.distribution.system.openapi.domain.dto.ApiChoosePhoneDTO;
import com.distribution.system.openapi.domain.dto.ApiOrderSearchDTO;
import com.distribution.system.openapi.domain.dto.ApiSendCodeDTO;
import com.distribution.system.openapi.domain.dto.ApiPlaceOrderDTO;
import com.distribution.system.openapi.domain.entity.CmccDaDownChannelInfo;
import com.distribution.system.openapi.domain.pojo.AddressInfo;
import com.distribution.system.openapi.service.CardDistributionApiService;
import com.distribution.system.openapi.service.CmccDaDownChannelInfoService;
import com.distribution.system.service.*;
import com.distribution.system.utils.EncryptionUtil;
import com.distribution.system.utils.http.HttpRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: GodLu
 * @create: 2024-04-19 11:35
 * @description: TODO
 */
@Slf4j
@Service
public class CardDistributionApiServiceImpl implements CardDistributionApiService {
    private static final Logger partnerChoosePhoneLog = LoggerFactory.getLogger("partnerChoosePhoneLog");
    private static final Logger partnerUnOrderLog = LoggerFactory.getLogger("partnerUnOrderLog");
    private static final Logger partnerSearchOrderLog = LoggerFactory.getLogger("partnerSearchOrderLog");
    private static final Logger partnerSmsCodeLog = LoggerFactory.getLogger("partnerSmsCodeLog");
    @Resource
    PlaceOrderOperationService placeOrderOperationService;
    @Resource
    CmccDaDownChannelInfoService cmccDaDownChannelInfoService;
    @Resource
    CmccDaProductService cmccDaProductService;
    @Resource
    AddressSystemService addressSystemService;
    @Resource
    CmccDaOrderService cmccDaOrderService;

    @Override
    public ReqResult sendVerifiedCode(ApiSendCodeDTO apiSendCodeDTO) {
        CmccDaDownChannelInfo one = cmccDaDownChannelInfoService.getOne(new LambdaQueryWrapper<CmccDaDownChannelInfo>()
                .eq(CmccDaDownChannelInfo::getDelFlag, 0)
                .eq(CmccDaDownChannelInfo::getAppId, apiSendCodeDTO.getAppid()), false);
        if (one == null) {
            log.error("商户不存在");
            partnerSmsCodeLog.error("商户不存在");
            throw new ApiParamValidException("商户不存在");
        }
        SendCodeDTO sendCodeDTO = new SendCodeDTO();
        // 根据产品编码查询号卡
        CmccDaProduct cmccDaProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                .eq(CmccDaProduct::getProductCode, apiSendCodeDTO.getProductCode())
                .eq(CmccDaProduct::getProductStatus, 1), false);//没有隐藏.
        if (cmccDaProduct == null) {
            log.error("商品编码参数异常");
            partnerSmsCodeLog.error("商品编码参数异常");
            throw new ApiParamValidException("商品编码参数异常");
        }
        sendCodeDTO.setProductCode(apiSendCodeDTO.getProductCode());
        sendCodeDTO.setCustomerPhone(apiSendCodeDTO.getPostMobile());
        if (cmccDaProduct.getProductTypeId() != 6) {
            sendCodeDTO.setCertName(apiSendCodeDTO.getName());
            sendCodeDTO.setCertNum(apiSendCodeDTO.getCard());
        }
        log.info("合作方调用获取验证码接口传递参数为：{}", sendCodeDTO);
        partnerChoosePhoneLog.info("合作方调用获取验证码接口传递参数为：{}", sendCodeDTO);
        ReqResult reqResult = placeOrderOperationService.sendVerificationCode(sendCodeDTO);
        log.info("合作方调用获取验证码接口返回结果为：{}", reqResult);
        partnerChoosePhoneLog.info("合作方调用获取验证码接口返回结果为：{}", reqResult);
        return reqResult;
    }

    @Override
    public ReqResult choosePhoneNumber(ApiChoosePhoneDTO apiChoosePhoneDto) {
        ChoosePhoneDTO choosePhoneDTO = new ChoosePhoneDTO();
        choosePhoneDTO.setPage(apiChoosePhoneDto.getPage());
        choosePhoneDTO.setProductCode(apiChoosePhoneDto.getProductCode());
        // 获取地区信息
        AddressInfo addressInfoParam = new AddressInfo();
        addressInfoParam.setAddressProvince(apiChoosePhoneDto.getAddressProvince());
        addressInfoParam.setAddressCity(apiChoosePhoneDto.getAddressCity());
        addressInfoParam.setAddressDistrict(apiChoosePhoneDto.getAddressArea());
        addressInfoParam.setAttributeProvince(apiChoosePhoneDto.getAttributionProvince());
        addressInfoParam.setAttributeCity(apiChoosePhoneDto.getAttributionCity());
        AddressInfo addressInfo = getAddressInfo(addressInfoParam);
        // 设置收货地和归属地信息
        choosePhoneDTO.setAddressProvince(addressInfo.getAddressProvince());
        choosePhoneDTO.setAddressProvinceCode(addressInfo.getAddressProvinceCode());
        choosePhoneDTO.setAddressCity(addressInfo.getAddressCity());
        choosePhoneDTO.setAddressCityCode(addressInfo.getAddressCityCode());
        choosePhoneDTO.setAddressDistrict(addressInfo.getAddressDistrict());
        choosePhoneDTO.setAddressDistrictCode(addressInfo.getAddressDistrictCode());
        choosePhoneDTO.setAttributeProvince(addressInfo.getAttributeProvince());
        choosePhoneDTO.setAttributeProvinceCode(addressInfo.getAttributeProvinceCode());
        choosePhoneDTO.setAttributeCity(addressInfo.getAttributeCity());
        choosePhoneDTO.setAttributeCityCode(addressInfo.getAttributeCityCode());
        if (StringUtils.isEmpty(choosePhoneDTO.getAttributeProvinceCode()) || StringUtils.isEmpty(choosePhoneDTO.getAttributeCityCode())) {
            log.error("选号归属地省市参数异常");
            partnerChoosePhoneLog.error("选号归属地省市参数异常");
            throw new ApiParamValidException("选号归属地省市参数异常");
        }
        // 设置用户信息
        choosePhoneDTO.setCertName(apiChoosePhoneDto.getName());
        choosePhoneDTO.setCertNum(apiChoosePhoneDto.getCard());
        choosePhoneDTO.setCustomerPhone(apiChoosePhoneDto.getCustomerPhone());
        choosePhoneDTO.setAddressStreet(apiChoosePhoneDto.getAddressStreet());
        if (!StringUtils.isEmpty(apiChoosePhoneDto.getKeywords()))
            choosePhoneDTO.setKeywords(apiChoosePhoneDto.getKeywords());
        log.info("合作方选号传递参数为：{}", choosePhoneDTO);
        partnerChoosePhoneLog.info("合作方选号传递参数为：{}", choosePhoneDTO);
        ReqResult reqResult = placeOrderOperationService.choosePhone(choosePhoneDTO);
        //partnerChoosePhoneLog.info("合作方调用选号接口传返回结果为：{}", reqResult);
        if (reqResult.getCode() == 200) {
            ChoosePhoneResultBO choosePhoneResultBO = (ChoosePhoneResultBO) reqResult.getData();
            JSONObject data = new JSONObject();
            data.put("uuid", choosePhoneResultBO.getUuid());
            List<Long> numArray = choosePhoneResultBO.getNumArray().stream().map(Long::valueOf).collect(Collectors.toList());
            data.put("numArray", numArray);
            reqResult.setData(data);
        }
        log.info("合作方选号返回结果为：{}", reqResult);
        partnerChoosePhoneLog.info("合作方选号返回结果为：{}", reqResult);
        return reqResult;
    }

    @Override
    public ReqResult placeOrder(ApiPlaceOrderDTO apiPlaceOrderDTO) {
        CmccDaDownChannelInfo one = getCmccDaDownChannelInfo(apiPlaceOrderDTO.getAppid());
        // 设置下单参数
        PlaceOrderDTO placeOrderDTO = new PlaceOrderDTO();
        //通过appid获取合作方userid
        placeOrderDTO.setUserId(EncryptionUtil.encodeBase64(String.valueOf(one.getUserId())));
        placeOrderDTO.setProductCode(apiPlaceOrderDTO.getProductCode());
        // 根据产品编码查询号卡
        CmccDaProduct cmccDaProduct = getProductByProductCode(apiPlaceOrderDTO.getProductCode());
        placeOrderDTO.setProductParam(cmccDaProduct.getProductParam());
        placeOrderDTO.setProductTypeId(cmccDaProduct.getProductTypeId());
        placeOrderDTO.setCustomerPhone(apiPlaceOrderDTO.getCustomerPhone());
        if (cmccDaProduct.getProductTypeId() != 6) {
            // 设置下单用户信息
            placeOrderDTO.setCustomerName(apiPlaceOrderDTO.getCustomerName());
            placeOrderDTO.setCustomerCertNo(apiPlaceOrderDTO.getCustomerCertNo());
            // 获取地区信息
            AddressInfo addressInfoParam = new AddressInfo();
            addressInfoParam.setAddressProvince(apiPlaceOrderDTO.getAddressProvince());
            addressInfoParam.setAddressCity(apiPlaceOrderDTO.getAddressCity());
            addressInfoParam.setAddressDistrict(apiPlaceOrderDTO.getAddressArea());
            addressInfoParam.setAttributeProvince(apiPlaceOrderDTO.getChoosePhoneProvince());
            addressInfoParam.setAttributeCity(apiPlaceOrderDTO.getChoosePhoneCity());
            AddressInfo addressInfo = getAddressInfo(addressInfoParam);
            // 设置收货地和归属地信息
            placeOrderDTO.setAddressProvince(addressInfo.getAddressProvince());
            placeOrderDTO.setAddressProvinceCode(addressInfo.getAddressProvinceCode());
            placeOrderDTO.setAddressCity(addressInfo.getAddressCity());
            placeOrderDTO.setAddressCityCode(addressInfo.getAddressCityCode());
            placeOrderDTO.setAddressDistrict(addressInfo.getAddressDistrict());
            placeOrderDTO.setAddressDistrictCode(addressInfo.getAddressDistrictCode());
            placeOrderDTO.setAttributeProvince(addressInfo.getAttributeProvince());
            placeOrderDTO.setAttributeProvinceCode(addressInfo.getAttributeProvinceCode());
            placeOrderDTO.setAttributeCity(addressInfo.getAttributeCity());
            placeOrderDTO.setAttributeCityCode(addressInfo.getAttributeCityCode());
            if (StringUtils.isEmpty(placeOrderDTO.getAttributeProvinceCode()) || StringUtils.isEmpty(placeOrderDTO.getAttributeCityCode())) {
                log.error("下单归属地参数异常");
                partnerUnOrderLog.error("下单归属地参数异常");
                throw new ApiParamValidException("下单归属地参数异常");
            }
            placeOrderDTO.setAddressStreet(apiPlaceOrderDTO.getAddressStreet());
            if (StringUtils.isEmpty(placeOrderDTO.getAddressProvinceCode()) || StringUtils.isEmpty(placeOrderDTO.getAddressCityCode())
                    || StringUtils.isEmpty(placeOrderDTO.getAddressDistrictCode()) || StringUtils.isEmpty(placeOrderDTO.getAddressStreet())) {
                log.error("下单收货地址参数异常");
                partnerUnOrderLog.error("下单收货地址参数异常");
                throw new ApiParamValidException("下单收货地址参数异常");
            }
        }
        // 设置订购路径
        placeOrderDTO.setSubscribePath(apiPlaceOrderDTO.getSubscribePath());
        // 设置其他可以为空的参数
        placeOrderDTO.setChoosePhone(apiPlaceOrderDTO.getChoosePhone());
        placeOrderDTO.setCode(apiPlaceOrderDTO.getCode());
        if (!StringUtils.isEmpty(apiPlaceOrderDTO.getUuid())) placeOrderDTO.setPhoneUuid(apiPlaceOrderDTO.getUuid());
        log.info("合作方下单传递参数为：{}", placeOrderDTO);
        partnerUnOrderLog.info("合作方下单传递参数为：{}", placeOrderDTO);
        ReqResult reqResult = placeOrderOperationService.placeOrder(placeOrderDTO);
        log.info("合作方下单返回结果为：{}", reqResult);
        partnerUnOrderLog.info("合作方下单返回结果为：{}", reqResult);
        return reqResult;
    }

    private AddressInfo getAddressInfo(AddressInfo addressInfo) {
        // 设置下单收货地址信息
        addressInfo.setAddressProvinceCode(addressSystemService.getProvinceCodeByName(addressInfo.getAddressProvince()));
        addressInfo.setAddressCityCode(addressSystemService.getCityCodeByName(addressInfo.getAddressCity()));
        addressInfo.setAddressDistrictCode(addressSystemService.getDistrictCodeByName(addressInfo.getAddressDistrict()));
        // 设置下单归属地信息
        addressInfo.setAttributeProvinceCode(addressSystemService.getProvinceCodeByName(addressInfo.getAttributeProvince()));
        addressInfo.setAttributeCityCode(addressSystemService.getCityCodeByName(addressInfo.getAttributeCity()));
        return addressInfo;
    }

    private CmccDaProduct getProductByProductCode(String productCode) {
        // 根据产品编码查询号卡
        CmccDaProduct cmccDaProduct = cmccDaProductService.getOne(new LambdaQueryWrapper<CmccDaProduct>()
                .eq(CmccDaProduct::getProductCode, productCode)
                .eq(CmccDaProduct::getProductStatus, 1), false);//没有隐藏.
        if (cmccDaProduct == null) {
            log.error("商品编码【{}】参数异常", productCode);
            partnerUnOrderLog.error("商品编码【{}】参数异常", productCode);
            throw new ApiParamValidException("商品编码参数异常");
        }
        return cmccDaProduct;
    }

    private CmccDaDownChannelInfo getCmccDaDownChannelInfo(String appId) {
        CmccDaDownChannelInfo one = cmccDaDownChannelInfoService.getOne(new LambdaQueryWrapper<CmccDaDownChannelInfo>()
                .eq(CmccDaDownChannelInfo::getDelFlag, 0)
                .eq(CmccDaDownChannelInfo::getAppId, appId), false);
        if (one == null) {
            log.error("API账号【{}】不存在", appId);
            partnerUnOrderLog.error("API账号【{}】不存在", appId);
            throw new ApiParamValidException("API账号不存在");
        }
        return one;
    }

    /**
     * @param apiOrderSearchDTO 订单查询信息
     * @Author: GodLu
     * @Date: 2024/4/20 15:48
     * @Description: 查询订单信息
     * @return: JSONObject
     */
    @Validated
    @Override
    public JSONArray searchOrder(@Validated ApiOrderSearchDTO apiOrderSearchDTO) {
        CmccDaDownChannelInfo one = getCmccDaDownChannelInfo(apiOrderSearchDTO.getAppid());
        String[] orderIds = apiOrderSearchDTO.getOrderIds().split(",");
        if (orderIds.length > 100) {
            log.error("最多一次性查询100条订单");
            partnerSearchOrderLog.error("最多一次性查询100条订单");
            throw new ApiParamValidException("最多一次性查询100条订单");
        }
        // 查询订单
        List<CmccDaOrder> cmccDaOrderList = cmccDaOrderService.list(new LambdaUpdateWrapper<CmccDaOrder>()
                .in(CmccDaOrder::getOrderId, Arrays.asList(orderIds)));
        if (cmccDaOrderList == null || cmccDaOrderList.isEmpty()) {
            log.error("订单不存在");
            partnerSearchOrderLog.error("订单不存在");
            throw new ApiParamValidException("订单不存在");
        }
        // 响应数据
        JSONArray returnJsonArray = new JSONArray();
        for (CmccDaOrder cmccDaOrder : cmccDaOrderList) {
            JSONObject returnJsonObj = new JSONObject();
            returnJsonObj.put("orderId", cmccDaOrder.getOrderId());//订单编号
            returnJsonObj.put("phone", cmccDaOrder.getChoosePhone());//订购号码
            returnJsonObj.put("sc_money", cmccDaOrder.getScMoney());//首冲金额
            returnJsonObj.put("order_status", cmccDaOrder.getOrderStatus());//0失败 1下单成功 2进行中 3已成功
            returnJsonObj.put("fail_reason", cmccDaOrder.getFailureReason());//失败原因，可能为空
            returnJsonObj.put("product_status", cmccDaOrder.getProductStatus());//产品状态
            returnJsonObj.put("creat_time", cmccDaOrder.getCreateTime());//下单时间
            returnJsonObj.put("update_time", cmccDaOrder.getCreateTime());//订单更新时间
            returnJsonArray.add(returnJsonObj);
        }
        return returnJsonArray;
    }

    @Override
    public void orderCallback(CmccDaOrder cmccDaOrder) {
        if (Objects.isNull(cmccDaOrder.getUserId())) {
            //throw new ApiParamValidException("当前回调订单缺少用户编号");
            return;
        }
        // 根据订单用户ID查询相应的下游代理
        CmccDaDownChannelInfo cmccDaDownChannelInfo = cmccDaDownChannelInfoService.getOne(new LambdaQueryWrapper<CmccDaDownChannelInfo>()
                .eq(CmccDaDownChannelInfo::getUserId, cmccDaOrder.getUserId()), false);
        if (cmccDaDownChannelInfo == null) {
            //throw new ServiceException("当前回调订单找不到所属下游代理或属于多个下游代理");
            return;
        }
        // 根据下游代理获取订单回调URL
        String orderCallbackUrl = cmccDaDownChannelInfo.getOrderCallbackUrl();
        if (!StringUtils.isEmpty(orderCallbackUrl)) {
            JSONObject callbackJsonObj = new JSONObject();
            callbackJsonObj.put("orderId", cmccDaOrder.getOrderId());//订单编号
            callbackJsonObj.put("phone", cmccDaOrder.getChoosePhone());//订购号码
            callbackJsonObj.put("order_status", cmccDaOrder.getOrderStatus());//0失败 1下单成功 2进行中 3已成功
            callbackJsonObj.put("fail_reason", cmccDaOrder.getFailureReason());//失败原因，可能为空
            callbackJsonObj.put("product_status", cmccDaOrder.getProductStatus());//产品状态
            callbackJsonObj.put("creat_time", cmccDaOrder.getCreateTime());//下单时间
            callbackJsonObj.put("update_time", cmccDaOrder.getCreateTime());//订单更新时间
            log.info("向{}回调订单状态{}", cmccDaDownChannelInfo.getChannelName(), callbackJsonObj.toString());
            HttpRequestUtils.sendPost(orderCallbackUrl, callbackJsonObj.toString());
        }
    }
}
